package com.mlick.a.leetcode;

import java.util.*;

/**
 * @author lixiangxin
 * @date 2020/9/7 11:40
 * 347. 前 K 个高频元素
 * 在这里，我们可以利用堆的思想：建立一个小顶堆，然后遍历「出现次数数组」：
 * <p>
 * 如果堆的元素个数小于 kk，就可以直接插入堆中。
 * 如果堆的元素个数等于 kk，则检查堆顶与当前出现次数的大小。
 * 如果堆顶更大，说明至少有 kk 个数字的出现次数比当前值大，故舍弃当前值；
 * 否则，就弹出堆顶，并将当前值插入堆中。
 * 遍历完成后，堆中的元素就代表了「出现次数数组」中前 kk 大的值
 **/
public class A347 {

    public int[] topKFrequent(int[] nums, int k) {

        Map<Integer, Integer> counts = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            counts.put(nums[i], counts.getOrDefault(nums[i], 0) + 1);
        }

        PriorityQueue<int[]> integers = new PriorityQueue<>(new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[1] - o2[1];
            }
        });

        counts.forEach((key, v) -> {
            if (integers.size() == k) {
                if (integers.peek()[1] < v) {
                    integers.poll();
                    integers.add(new int[]{key, v});
                }
            } else {
                integers.add(new int[]{key, v});
            }
        });

        int[] rets = new int[k];
        for (int i = 0; i < k; i++) {
            rets[i] = integers.poll()[0];
        }

        return rets;
    }
}
